//  Inside Microsoft Exchange 2007 Web Services 
//  Chapter 1 
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.
//  All rights reserved.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;

namespace RawSOAPCall
{
    class Program
    {
        static void Main(string[] args)
        {
            // Build up our request (Listing 1-11)
            //
            StringBuilder request = new StringBuilder();
            request.AppendLine("<GetFolder>");
            request.AppendLine("    <FolderShape>");
            request.AppendLine("        <t:BaseShape>AllProperties</t:BaseShape>");
            request.AppendLine("    </FolderShape>");
            request.AppendLine("    <FolderIds>");
            request.AppendLine("        <t:DistinguishedFolderId Id=\"inbox\"/>");
            request.AppendLine("    </FolderIds>");
            request.AppendLine("</GetFolder>");

            // Make the request using our helper method
            //
            XmlDocument doc = MakeRawSoapRequest(
                                    @"https://yourserver/ews/Exchange.asmx",
                                    "username",
                                    "password",
                                    "domain", 
                                    request.ToString());

            // Write out the response to the console
            //
            Console.WriteLine(doc.OuterXml);
        }

        /// <summary>
        /// Makes a raw soap request (Listing 1-10)
        /// </summary>
        /// <param name="url">URL of server to talk to</param>
        /// <param name="userName">UserName</param>
        /// <param name="password">Password</param>
        /// <param name="domain">User's domain</param>
        /// <param name="EWSRequestString">The contents of the soap body (minus the body element)</param>
        /// <param name="headers">PARAMS any soap headers to add</param>
        /// <returns>DOM wrapper around the response</returns>
        /// 
        static XmlDocument MakeRawSoapRequest(
                                string url,
                                string userName,
                                string password,
                                string domain,
                                string EWSRequestString,
                                params string[] headers)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "text/xml;utf-8";
            request.Credentials = new NetworkCredential(userName, password, domain);

            StringBuilder builder = new StringBuilder();
            builder.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            builder.AppendLine("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
            builder.AppendLine("               xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"");
            builder.AppendLine("               xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"");
            builder.AppendLine("               xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\"");
            builder.AppendLine("               xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">");
            // Add the soap headers if present
            //
            if ((headers != null) && (headers.Length > 0))
            {
                builder.AppendLine("<soap:Header>");
                foreach (string header in headers)
                {
                    builder.Append(header);
                }
                builder.AppendLine("</soap:Header>");
            }
            builder.AppendLine("<soap:Body>");
            // Add the passed request
            //
            builder.Append(EWSRequestString);
            builder.AppendLine("</soap:Body>");
            builder.AppendLine("</soap:Envelope>");

            // Grab the request as a byte array
            //
            byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes(builder.ToString());

            request.ContentLength = requestBytes.Length;

            // Write our request bytes to the web request
            //
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(requestBytes, 0, requestBytes.Length);
                requestStream.Flush();
                requestStream.Close();
            }
            HttpWebResponse response;
            try
            {
                // Try to get the response
                //
                response = request.GetResponse() as HttpWebResponse;
            }
            catch (WebException webException)
            {
                HttpWebResponse httpResponse = webException.Response as HttpWebResponse;
                using (Stream responseStream = httpResponse.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(responseStream))
                    {
                        throw new Exception(reader.ReadToEnd());
                    }
                }
            }

            // Read the response stream
            //
            string responseString;
            using (Stream responseStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(responseStream))
                {
                    responseString = reader.ReadToEnd();
                }
            }

            // Now we have our response.  Load it into the DOM
            //
            XmlDocument doc = new XmlDocument();
            int xmlStartIndex = responseString.IndexOf("<?xml");
            doc.LoadXml(responseString.Substring(xmlStartIndex));
            return doc;
        }
    }
}
